package com.a1573595.musicplayer.player

import android.app.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.*
import android.provider.MediaStore
import android.util.Log
import android.widget.RemoteViews
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.a1573595.musicplayer.R
import com.a1573595.musicplayer.Weak
import com.a1573595.musicplayer.model.Song
import com.a1573595.musicplayer.player.PlayerManager.Companion.ACTION_COMPLETE
import com.a1573595.musicplayer.player.PlayerManager.Companion.ACTION_PAUSE
import com.a1573595.musicplayer.player.PlayerManager.Companion.ACTION_PLAY
import com.a1573595.musicplayer.player.PlayerManager.Companion.ACTION_STOP
import com.a1573595.musicplayer.songList.SongListActivity
import com.mpatric.mp3agic.Mp3File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.beans.PropertyChangeEvent
import java.beans.PropertyChangeListener
import java.io.FileDescriptor
import java.lang.Exception

class PlayerService : Service(), PropertyChangeListener {
    companion object {
        const val CHANNEL_ID_MUSIC = "app.MUSIC"
        const val CHANNEL_NAME_MUSIC = "Music"
        const val NOTIFICATION_ID_MUSIC = 101

        const val BROADCAST_ID_MUSIC = 201
        const val NOTIFICATION_PREVIOUS = "notification.PREVIOUS"
        const val NOTIFICATION_PLAY = "notification.PLAY"
        const val NOTIFICATION_NEXT = "notification.NEXT"
        const val NOTIFICATION_CANCEL = "notification.CANCEL"

        const val ACTION_FIND_NEW_SONG = "action.FIND_NEW_SONG"
        const val ACTION_NOT_SONG_FOUND = "action.NOT_FOUND"
    }

    private lateinit var smallRemoteView: RemoteViews
    private lateinit var largeRemoteView: RemoteViews
    private lateinit var intentPREVIOUS: PendingIntent
    private lateinit var intentPlay: PendingIntent
    private lateinit var intentNext: PendingIntent
    private lateinit var intentCancel: PendingIntent
    private val handler = Handler(Looper.getMainLooper())//用于更新歌词
    private lateinit var updateLyricPositionRunnable: Runnable//用于更新歌词

    private val receiver = object : BroadcastReceiver() {
        override fun onReceive(p0: Context?, intent: Intent?) {
            when (intent?.action) {
                NOTIFICATION_PREVIOUS -> skipToPrevious()
                NOTIFICATION_PLAY -> {
                    if (isPlaying) {
                        pause()
                    } else {
                        play()
                    }
                }
                NOTIFICATION_NEXT -> skipToNext()
                NOTIFICATION_CANCEL -> {
                    pause()

                    stopForeground(true)
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        stopForeground(STOP_FOREGROUND_DETACH)
                    }

                    stopSelf()
                }
            }
        }
    }

    private val metaRetriever = MediaMetadataRetriever()
    private val uriExternal: Uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    private val mHandler: Handler = Handler(Looper.getMainLooper()) { msg ->
        val id = msg.data.getString("songID")
        val audioUri = Uri.withAppendedPath(uriExternal, id)

        try {
            contentResolver.openFileDescriptor(audioUri, "r")?.use {
                val filePath = getFilePathFromUri(audioUri)
                if (addSong(it.fileDescriptor, id!!, getSongTitle(audioUri),filePath)) {
                    playerManager.setChangedNotify(ACTION_FIND_NEW_SONG)
                }
            }
        } catch (e: Exception) {
            Timber.e(e)
        }

        true
    }
    private val audioObserver: AudioObserver = AudioObserver(mHandler)

    private val playerManager: PlayerManager = PlayerManager()

    private val songList: MutableList<Song> = mutableListOf()
    private var playerPosition: Int = 0    // 当前播放歌曲的位置
    private var isPlaying: Boolean = false // 是否正在播放
    var isRepeat: Boolean = false
    var isRandom: Boolean = false
    var parsedLyrics: List<Pair<Int, String>> = emptyList()//这个是用于展示在LyricsActivity歌词的
    var currentLyricPosition: Int = 0
    inner class LocalBinder : Binder() {
        val service by Weak {
            this@PlayerService
        }
        var parsedLyrics: List<Pair<Int, String>> =emptyList()//展示在playSong下的一段歌词
        var dic_picture: Bitmap? = null
    }

     var binder: LocalBinder? = null

    override fun onCreate() {
        super.onCreate()

        createNotificationChannel()
        initRemoteView()

        contentResolver.registerContentObserver(uriExternal, true, audioObserver)
        registerReceiver()
        addPlayerObserver(this)

        binder = LocalBinder()
    }

    override fun onBind(intent: Intent): IBinder? {
        return binder
    }

    override fun onTaskRemoved(rootIntent: Intent) {
        super.onTaskRemoved(rootIntent)

        stopSelf()
    }

    override fun onDestroy() {
        binder = null

        contentResolver.unregisterContentObserver(audioObserver)
        unregisterReceiver(receiver)
        metaRetriever.release()

        deletePlayerObserver(this)
        playerManager.stop()

        super.onDestroy()
    }

    override fun propertyChange(event: PropertyChangeEvent) {
        when (event.propertyName) {
            ACTION_COMPLETE -> {
                playerManager.setPlayerProgress(0)

                when {
                    isRepeat -> play()
                    isRandom -> play((0 until songList.size).random())
                    else -> skipToNext()
                }
            }
            ACTION_PLAY, ACTION_PAUSE -> {
                startForeground(NOTIFICATION_ID_MUSIC, createNotification())
            }
            ACTION_STOP -> {
                isPlaying = false
            }
            ACTION_FIND_NEW_SONG -> {
                Toast.makeText(this, getString(R.string.found_new_song), Toast.LENGTH_SHORT).show()
            }
            ACTION_NOT_SONG_FOUND -> {
                Toast.makeText(this, getString(R.string.no_song_found), Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun addSong(fd: FileDescriptor, id: String, title: String,filePath: String): Boolean {
        try {
            if (!fd.valid()) {
                return false
            }

            metaRetriever.setDataSource(fd)

            val duration =
                metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
            val artist =
                metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
            val author =
                metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR)

            if (duration.isNullOrEmpty()) {
                return false
            }

            val song = Song(
                id,
                title,
                artist ?: author ?: getString(R.string.unknown),
                duration.toLong(),
                filePath // 添加文件路径
            )

            if (!songList.contains(song)) {//没有这首歌就添加
                songList.add(song)
            }
        } catch (e: Exception) {
            Timber.e(e)
            return false
        }
        return true
    }

    suspend fun readSong() = withContext(Dispatchers.IO) {
        if (songList.isNotEmpty()) return@withContext

        contentResolver.query(
            uriExternal, null, null, null,
            null
        )?.use {
            val indexID: Int = it.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
            val indexTitle: Int = it.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
            val indexData: Int = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA) // 获取文件路径

            while (it.moveToNext()) {
                val id = it.getString(indexID)
                val title = it.getString(indexTitle)
                val filePath = it.getString(indexData) // 获取文件路径
                val audioUri = Uri.withAppendedPath(uriExternal, id)

                contentResolver.openFileDescriptor(audioUri, "r")?.use {
                    addSong(it.fileDescriptor, id, title,filePath)
                }
            }
        }
    }

    fun addPlayerObserver(listener: PropertyChangeListener) =
        playerManager.addPropertyChangeListener(listener)

    fun deletePlayerObserver(listener: PropertyChangeListener) =
        playerManager.removePropertyChangeListener(listener)

    fun isPlaying(): Boolean = isPlaying

    fun getSongList() = songList.toList()

    fun getSong(): Song? {//获取当前播放歌曲
        return if (songList.size > 0) {
            songList[playerPosition]
        } else {
            null
        }
    }

    fun getProgress(): Int = playerManager.getPlayerProgress()

    fun play(position: Int = playerPosition) {//播放指定位置的歌曲，并更新下方歌词。

        binder?.parsedLyrics = parseLyrics(getLyricsForCurrentSong()) // 更新歌词

        binder?.dic_picture = getArtworkForCurrentSong()//更新封面
        Log.d("picture", "封面图片上：${getArtworkForCurrentSong()}")


        parsedLyrics=parseLyrics(getLyricsForCurrentSong())

        isPlaying = true

        if (position != playerPosition) {   // 如果播放的是当前歌曲，不需要重新设置
            playerManager.setPlayerProgress(0)//设置播放进度为0
        }

        playerPosition = when {//判断播放位置是否合法
            songList.size < 1 -> {
                playerManager.setChangedNotify(ACTION_NOT_SONG_FOUND)
                return
            }
            position >= songList.size -> 0
            position < 0 -> songList.lastIndex
            else -> position
        }

        val audioUri = Uri.withAppendedPath(uriExternal, songList[playerPosition].id)

        contentResolver.openFileDescriptor(audioUri, "r")?.use {
            playerManager.play(it.fileDescriptor)
            binder?.parsedLyrics = parseLyrics(getLyricsForCurrentSong()) // 更新歌词
            binder?.dic_picture = getArtworkForCurrentSong()//更新封面
            Log.d("picture", "封面图片下：${getArtworkForCurrentSong()}")
            parsedLyrics=parseLyrics(getLyricsForCurrentSong())
            updateParsedLyrics()// 更新歌词
        } ?: kotlin.run {
            songList.removeAt(playerPosition)
            playerManager.setChangedNotify(ACTION_NOT_SONG_FOUND)

            play()
        }
        //playerManager.setPlayerProgress(0)//设置播放进度为0
    }
    private fun updateParsedLyrics() {//更新歌词，用于展示在LyricsActivity
        val lyrics = getLyricsForCurrentSong()
        binder?.parsedLyrics = parseLyrics(lyrics)
        parsedLyrics=parseLyrics(getLyricsForCurrentSong())
    }

    fun pause() {//暂停
        isPlaying = false

        playerManager.pause()
    }

    fun seekTo(progress: Int) {//跳到指定进度
        if (isPlaying) {
            playerManager.seekTo(progress)
        } else {
            playerManager.setPlayerProgress(progress)
            play()
        }
    }

    fun skipToNext() {//跳到下一首
        if (!isRandom) {
            play(playerPosition + 1)
        } else {
            play((0 until songList.size).random())
        }
    }

    fun skipToPrevious() {//跳到上一首
        if (!isRandom) {
            play(playerPosition - 1)
        } else {
            play((0 until songList.size).random())
        }
    }

    private fun getSongTitle(uri: Uri): String {//通过uri获取歌曲标题
        var title: String? = uri.lastPathSegment

        contentResolver.query(
            uri, null, null, null,
            null
        )?.use {
            if (it.moveToNext()) {
                title = it.getString(it.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE))
            }
        }

        return title ?: ""
    }

    private fun createNotificationChannel() {//创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val nm = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

            val status = NotificationChannel(
                CHANNEL_ID_MUSIC,
                CHANNEL_NAME_MUSIC, NotificationManager.IMPORTANCE_LOW
            )
            status.description = "Music player"
            nm.createNotificationChannel(status)
        }
    }

    private fun initRemoteView() {//初始化RemoteView
        smallRemoteView = RemoteViews(packageName, R.layout.notification_small)//小通知初始化
        largeRemoteView = RemoteViews(packageName, R.layout.notification_large)//大通知初始化

        intentPREVIOUS = PendingIntent.getBroadcast(//广播实现上一首
            this, BROADCAST_ID_MUSIC,
            Intent(NOTIFICATION_PREVIOUS).setPackage(packageName),  //发送广播
            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        intentPlay = PendingIntent.getBroadcast(//实现播放
            this, BROADCAST_ID_MUSIC,
            Intent(NOTIFICATION_PLAY).setPackage(packageName),
            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        intentNext = PendingIntent.getBroadcast(//实现下一首
            this, BROADCAST_ID_MUSIC,
            Intent(NOTIFICATION_NEXT).setPackage(packageName),
            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        intentCancel = PendingIntent.getBroadcast(//实现关闭
            this, BROADCAST_ID_MUSIC,
            Intent(NOTIFICATION_CANCEL).setPackage(packageName),
            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
    }

    private fun registerReceiver() {//注册广播接收器
        val intentFilter = IntentFilter()
        intentFilter.addAction(NOTIFICATION_PREVIOUS)
        intentFilter.addAction(NOTIFICATION_PLAY)
        intentFilter.addAction(NOTIFICATION_NEXT)
        intentFilter.addAction(NOTIFICATION_CANCEL)
        registerReceiver(receiver, intentFilter)
    }

    private fun createNotification(): Notification {//创建通知
        val song = getSong()

        smallRemoteView.setTextViewText(R.id.tv_name, song?.name)
        smallRemoteView.setImageViewResource(
            R.id.img_play,
            if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
        )

        largeRemoteView.setTextViewText(R.id.tv_name, song?.name)
        largeRemoteView.setImageViewResource(
            R.id.img_play,
            if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
        )
        largeRemoteView.setOnClickPendingIntent(R.id.img_previous, intentPREVIOUS)
        largeRemoteView.setOnClickPendingIntent(R.id.img_play, intentPlay)
        largeRemoteView.setOnClickPendingIntent(R.id.img_next, intentNext)
        largeRemoteView.setOnClickPendingIntent(R.id.img_cancel, intentCancel)

        val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID_MUSIC)
        notificationBuilder.setSmallIcon(R.drawable.ic_music)
//            .setLargeIcon(BitmapFactory.decodeResource(this.resources, R.drawable.music))
            .setContentTitle(song?.name)
            .setContentText(song?.author)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .setOnlyAlertOnce(true)
            .setContentIntent(createContentIntent())
            .setStyle(NotificationCompat.DecoratedCustomViewStyle())
            .setCustomContentView(smallRemoteView)
            .setCustomBigContentView(largeRemoteView)    //show full remoteView
//            .setOngoing(true) // not working when use startForeground()

        return notificationBuilder.build()
    }

    private fun createContentIntent(): PendingIntent {//创建一个PendingIntent，用于启动SongListActivity。
        val intent = Intent(this, SongListActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        intent.action = Intent.ACTION_MAIN
        intent.addCategory(Intent.CATEGORY_LAUNCHER)

        return PendingIntent.getActivity(
            this, System.currentTimeMillis().toInt(), intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
    }
    private fun getFilePathFromUri(uri: Uri): String {//通过uri获取文件路径
        var filePath = ""
        val projection = arrayOf(MediaStore.Audio.Media.DATA)
        contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
            if (cursor.moveToFirst()) {
                val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)
                filePath = cursor.getString(columnIndex)
            }
        }
        return filePath
    }
    private fun getArtworkForCurrentSong(): Bitmap? {
        return try {
            val mp3File = Mp3File(songList[playerPosition].filePath) // 使用当前播放歌曲
            val id3v2Tag = mp3File.id3v2Tag

            if (id3v2Tag != null && id3v2Tag.albumImage != null) {
                val albumImageData = id3v2Tag.albumImage // 获取封面图片的字节数据
                BitmapFactory.decodeByteArray(albumImageData, 0, albumImageData.size)
            } else {
                Log.d("picture", "无内置图片")
                null // 无封面图片
            }
        } catch (e: Exception) {
            Timber.e(e, "封面图片读取失败")
            null
        }
    }


    private fun getLyricsForCurrentSong(): String {//获取当前播放歌曲的歌词
        return try {
            val mp3File = Mp3File(songList[playerPosition].filePath)  // 使用当前播放歌曲
            val id3v2Tag = mp3File.id3v2Tag
            if (id3v2Tag != null && id3v2Tag.lyrics != null) {
                id3v2Tag.lyrics
            } else {
                "无歌词"
            }
        } catch (e: Exception) {
            Timber.e(e)
            "歌词读取失败"
        }
    }
    private fun parseLyrics(lyrics: String): List<Pair<Int, String>> {//解析歌词
        val lyricsList = mutableListOf<Pair<Int, String>>()
        val lines = lyrics.lines()
        val timeRegex = Regex("\\[(\\d{2}):(\\d{2})\\.(\\d{2})]")

        for (line in lines) {
            val matches = timeRegex.findAll(line)
            val text = line.replace(timeRegex, "").trim()

            for (match in matches) {
                val (minutes, seconds, milliseconds) = match.destructured
                val time = minutes.toInt() * 60 * 1000 + seconds.toInt() * 1000 + milliseconds.toInt() * 10
                lyricsList.add(Pair(time, text))
                Log.d("LyricsDebug", "Time: $time, Text: $text")
            }
        }

        //Log.d("LyricsDebug", "Parsed lyricsList: $lyricsList")
        return lyricsList.sortedBy { it.first }
    }


}